package com.myc.demo.servletFrame.servlet;

import com.myc.demo.servletFrame.annotation.MYCController;
import com.myc.demo.servletFrame.annotation.MYCService;

import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.*;

/**
 * @auther 木玉川/ybs_0921@163.com
 * @date 2018/12/23 9:46
 */
public class YC_ServletFrameWork extends HttpServlet {

    private Properties contextConfig = new Properties();

    private List<String> classNames = new ArrayList<String>();//扫描到的所有的类名称

    private Map<String,Object> ioc = new HashMap<String,Object>();

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        this.doPost(req,resp);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //6，等待
        doDispatcher();
    }

    private void doDispatcher() {
    }


    @Override
    public void init(ServletConfig config) throws ServletException {
        //1，加载配置文件
        doLoadConfig(config.getInitParameter("contextConfigLocation"));
       
       
        //2，扫描所有相关联的类
        doScanner(contextConfig.getProperty("scan-Package"));
        
        //3，初始化所有相关联的类，并将其保存到IOC容器中
        try {
            doInstance();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        }


        //4，自动实现依赖注入DI
        doAutowired();


        //5，初始化HandlerMapping
        doInitHanderMapping();

    }

    private void doInitHanderMapping() {
    }

    private void doAutowired() {
    }

    private void doInstance() throws IllegalAccessException, InstantiationException {
        if(classNames==null){return;}
        for (String className:classNames) {
            try {
                Class<?> clazz = Class.forName(className);
                //进行初始化
                //不是所有类都需要初始化
                // clazz.newInstance();
                //只有加了注解的类才需要初始化
                if(clazz.isAnnotationPresent(MYCController.class)){

                    //初始化之后保存到IOD容器中
                    //key的规则
                    //1，默认类名首字母小写
                    //2。自定义类名
                    //3，接口全类名作为yey，以实现类的实例作为值保存
                    String beanName = toLowerFirstCase(clazz.getSimpleName());//获取类名
                    ioc.put(beanName,clazz.newInstance());

                }else if(clazz.isAnnotationPresent(MYCService.class)){
                    //1，默认类名首字母小写
                    //2。自定义类名
                    //3，接口全类名作为yey，以实现类的实例作为值保存
                    MYCService service = clazz.getAnnotation(MYCService.class);
                    String beanName = service.value();//service("aa")service注解括号里面可以指定参数
                    if("".equals(beanName.trim())){
                        beanName = toLowerFirstCase(clazz.getSimpleName());
                    }

                    Object instance  = clazz.newInstance();
                    ioc.put(beanName,instance);

                    Class<?>[] interfaces =  clazz.getInterfaces();
                    for (Class<?> i:interfaces) {
                        //if (ioc.containsKey())  接口有多个实现类，要处理的
                        ioc.put(i.getName(),instance);
                    }
                }else{
                    //没有加注解的类直接忽略
                    continue;
                }
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }
        }
    }

    private void doScanner(String scanPackage) {
         URL url = this.getClass().getResource("/"+scanPackage.replaceAll("\\.","/"));//类路径
         File classDir = new File(url.getFile());
        for (File file:classDir.listFiles()) {
            if (file.isDirectory()){
                doScanner(scanPackage+"."+file.getName());
            }else{
                String className = (scanPackage+"."+file.getName()).replace(".class","");
                classNames.add(className);//所有扫描到的类存起来
            }
        }

    }

    private void doLoadConfig(String contextConfigLocation) {
        InputStream ins =this.getClass().getClassLoader().getResourceAsStream(contextConfigLocation);
        try {
            contextConfig.load(ins);
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            if(ins!=null){
                try {
                    ins.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    //类首字母小写
    private String toLowerFirstCase(String str){
        char[] chars = str.toCharArray();
        chars[0] += 32;//大写字母与小写字母阿斯玛差了32
        return String.valueOf(chars);
    }

}
